﻿// MessageQueue.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <queue>
#include <thread>
#include <chrono>
#include <memory>
#include <condition_variable>
#include <windows.h>

using namespace std;

typedef struct task_tag
{
    int data;
    task_tag(int i) :data(i) {}
}Task, *PTask;

class MessageQueue
{
public:
    MessageQueue() {};
    ~MessageQueue()
    {
        if (!m_queue.empty())//队列不为空
        {
            PTask pRtn = m_queue.front();//返回队列第一个元素的引用
            delete pRtn;
        }
    }

    void PushTask(PTask pTask)
    {
        unique_lock<mutex> lock(m_queueMutex);
        m_queue.push(pTask);
        m_cond.notify_one();
    }

    PTask PopTask()
    {
        PTask pRtn = NULL;
        unique_lock<mutex> lock(m_queueMutex);
        while (m_queue.empty())//队列为空
        {
            m_cond.wait_for(lock, chrono::seconds(1));
        }

        if (!m_queue.empty())//队列不为空
        {
            pRtn = m_queue.front();//返回队列第一个元素的引用
            if (pRtn->data != 0)
            {
                m_queue.pop();//函数删除队列的一个元素
            }
        }
        return pRtn;
    }
protected:
private:
    mutex m_queueMutex;
    condition_variable m_cond;
    queue<PTask> m_queue;
};

void thread_fun(MessageQueue* arguments)
{
    while (true)
    {
        PTask data = arguments->PopTask();
        if (data != NULL)
        {
  //          printf("Thread is: %d\n", std::this_thread::get_id());
            printf("   %d\n", data->data);
            if (0 == data->data) //Thread end;
                break;
            else
                delete data;
        }
        Sleep(500);
    }
    return;
}

int main()
{
    MessageQueue cq;
#define  THREAD_NUM 3
    std::thread threads[THREAD_NUM];

    for (int i = 0; i<THREAD_NUM; i++)
    {
        threads[i] = std::thread(thread_fun, &cq);
    }
#if 1
    int i = 100000;
    while (i > 0)
    {
        //添加元素
        Task* pTask = new Task( --i );
        cq.PushTask(pTask);
    }
    //释放线程
    for (size_t i = 0; i < THREAD_NUM; i++)
    {
        threads[i].join();
    }
#endif
    while (true)
    {
        ::Sleep(1000);

    }
    return 0;
}
